import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { agencyAsync, appoxCallback } from '@/appox/appox'
import { appoxUtility } from '@/appox/appox'
import { AppoxSignalsData } from '@/appox/appox'
import { AppoxFloatPoint } from '@/appox/appox'

export const useSignalMonitorStore = defineStore('signalMonitor', () => {
  // 状态
  const monitors = ref([])
  const isUpdating = ref(false)
  const MAX_MONITORS = 10
  const canvasRefs = ref(new Map())  // 添加 canvasRefs

  // 数据
  let signalBuffer = {}

  // 计算属性
  const canAddMore = computed(() => monitors.value.length < MAX_MONITORS)

  // 持久化相关函数
  function saveToLocalStorage() {
    const signalIds = monitors.value.map(monitor => monitor.signalId)
    localStorage.setItem('AppoxJsTest.SignalMonitorIDs', JSON.stringify(signalIds))
  }

  function loadFromLocalStorage() {
    const savedIds = localStorage.getItem('AppoxJsTest.SignalMonitorIDs')
    if (savedIds) {
      try {
        const signalIds = JSON.parse(savedIds)
        addMonitors(signalIds)
      } catch (error) {
        console.error('Failed to load saved signal IDs:', error)
      }
    }
  }

  // 动作
  let count = 0
  function addMonitors(signalIds) {
    if (!signalIds || !Array.isArray(signalIds)) return
    
    const remainingSlots = MAX_MONITORS - monitors.value.length
    const newSignals = signalIds.slice(0, remainingSlots)
    
    newSignals.forEach(signalId => {
      const newMonitor = {
        id: count++,
        signalId,
        name: signalId, // 将在updateSignalInfo中更新
        value: null,
        trend: [], // AppoxFloatPoint数组
        isRunning: false
      }
      monitors.value.push(newMonitor)
      agencyAsync.addSignalReference(newMonitor.signalId)
      signalBuffer[newMonitor.signalId] = []
    })

    // 保存到localStorage
    saveToLocalStorage()
  }

  function removeMonitor(monitorId) {
    const index = monitors.value.findIndex(m => m.id === monitorId)
    if (index !== -1) {
      const monitor = monitors.value[index]
      agencyAsync.removeSignalReference(monitor.signalId)
      delete signalBuffer[monitor.signalId]
      monitors.value.splice(index, 1)
      
      // 保存到localStorage
      saveToLocalStorage()
    }
  }

  function onReconnected() {
    monitors.value.forEach(monitor => {
      agencyAsync.addSignalReference(monitor.signalId)
    })
  }

  function onResetData() {
    for (const signalId in signalBuffer) {
      signalBuffer[signalId] = []
    }
  }

  function onInputData(data) {
    if (data instanceof AppoxSignalsData) {
        let buffer = signalBuffer[data.signalID]
        if (buffer == null) return

        let samples = data.toSamples()
        if (samples == null) return

        for (let sample of samples) {
            buffer.push(sample)
        }
        appoxUtility.clipSampleBuffer(buffer)
    }
  }

  async function updateSignalInfo() {
    if (isUpdating.value) return
    
    try {
      isUpdating.value = true
      
      // 并行更新所有信号
      await Promise.all(monitors.value.map(updateSingleSignal))
    } catch (error) {
      console.error('Failed to update signal info:', error)
    } finally {
      isUpdating.value = false
    }
  }

  // 更新单个信号的信息
  async function updateSingleSignal(monitor) {
    try {
      // 获取信号信息
      const signalName = await agencyAsync.getSignalName(monitor.signalId, true)
      if (signalName) {
        monitor.name = signalName
      }

      // 获取信号值
      let interest = appoxUtility.getInterestTimeLocal();
      let globalInterestIndex = null;
      if (signalBuffer[monitor.signalId] == null) monitor.value = null
      else {
        let searchResult = appoxUtility.searchSample(signalBuffer[monitor.signalId], interest, 1.0)
        monitor.value = searchResult == null ? null : formatSignalValue((searchResult.weight1 > searchResult.weight2 ? searchResult.sample1 : searchResult.sample2).value)
        globalInterestIndex = searchResult == null ? null : (searchResult.weight1 > searchResult.weight2 ? searchResult.index1 : searchResult.index2)
      }

      // 更新趋势数据
      if (signalBuffer[monitor.signalId] == null) monitor.trend = []
      else {
        let lower = Math.max(0.0, interest - 10)
        let upper = interest + 10
        let lowerSearchResult = appoxUtility.searchSample(signalBuffer[monitor.signalId], lower, interest - lower + 1)
        let upperSearchResult = appoxUtility.searchSample(signalBuffer[monitor.signalId], upper, upper - interest + 1)
        let lowerIndex = lowerSearchResult == null ? null : lowerSearchResult.index2
        let upperIndex = upperSearchResult == null ? null : upperSearchResult.index1
        let localInterestIndex = null;
        if (lowerIndex == null || upperIndex == null || upperIndex <= lowerIndex) {
          monitor.trend = []
        } else {
          monitor.trend = signalBuffer[monitor.signalId].slice(lowerIndex, upperIndex + 1).map(sample => new AppoxFloatPoint(sample.timeline, sample.value))
          localInterestIndex = globalInterestIndex == null || globalInterestIndex < lowerIndex || globalInterestIndex > upperIndex ? null : (globalInterestIndex - lowerIndex)
        }
        drawTrendChart(monitor.id, localInterestIndex)
      }
      
    } catch (error) {
      console.error(`Failed to update signal ${monitor.signalId}:`, error)
    }
  }

  // 格式化信号值显示
  function formatSignalValue(value) {
    if (typeof value !== 'number') return null
    
    // 如果是整数，直接返回
    if (Number.isInteger(value)) return value
    
    // 对于小数，保留8位有效数字
    return Math.abs(value) < 1 ? Number(value.toFixed(8)) : Number(value.toPrecision(8))
  }

  // 绘制趋势图
  function drawTrendChart(monitorId, localInterestIndex) {
    const canvas = getCanvasRef(monitorId)
    if (!canvas) return

    const monitorIndex = monitors.value.findIndex(m => m.id === monitorId)
    if (monitorIndex == -1) return

    const monitor = monitors.value[monitorIndex]

    // 调整 canvas 的实际尺寸以匹配其显示尺寸
    const rect = canvas.getBoundingClientRect()
    canvas.width = rect.width
    canvas.height = rect.height

    const ctx = canvas.getContext('2d')
    const width = canvas.width
    const height = canvas.height

    // 计算绘图区域
    const paddingX = 8
    const paddingY = 8
    const plotWidth = width - 16
    const plotHeight = height - 16

    // 清除画布
    ctx.clearRect(0, 0, width, height)

    // 获取数据点
    const points = monitor.trend
    if (points.length < 2) return

    // 计算数据范围
    const min = Math.min(...points.map(point => point.y))
    const max = Math.max(...points.map(point => point.y))
    const range = max - min || 1 // 避免除以0

    // 设置样式
    ctx.strokeStyle = getComputedStyle(document.documentElement)
      .getPropertyValue('--el-color-primary')
    ctx.lineWidth = 2

    // 开始绘制
    ctx.beginPath()
    points.forEach((point, index) => {
      const x = paddingX + (index / (points.length - 1)) * plotWidth
      const y = paddingY + plotHeight - ((point.y - min) / range) * plotHeight
      if (index === 0) {
        ctx.moveTo(x, y)
      } else {
        ctx.lineTo(x, y)
      }
    })
    ctx.stroke()

    // 如果存在 localInterestIndex，在对应位置绘制空心圆
    if (localInterestIndex !== null && localInterestIndex >= 0 && localInterestIndex < points.length) {
      const point = points[localInterestIndex]
      const x = paddingX + (localInterestIndex / (points.length - 1)) * plotWidth
      const y = paddingY + plotHeight - ((point.y - min) / range) * plotHeight

      // 绘制空心圆
      ctx.beginPath()
      ctx.arc(x, y, 4, 0, Math.PI * 2)
      ctx.strokeStyle = getComputedStyle(document.documentElement)
        .getPropertyValue('--el-color-primary')
      ctx.lineWidth = 2
      ctx.stroke()
    }
  }

  async function showSignalAdder() {
    const selectedIds = monitors.value.map(m => m.signalId)
    const newSignalIds = await appoxCallback.onSelectSignals(selectedIds, MAX_MONITORS - monitors.value.length)
    if (newSignalIds && newSignalIds.length > 0) {
      addMonitors(newSignalIds)
    }
  }

  // 设置 canvas 引用
  function setCanvasRef(el, monitorId) {
    if (el) {
      canvasRefs.value.set(monitorId, el)
    }
  }

  // 获取 canvas 引用
  function getCanvasRef(monitorId) {
    return canvasRefs.value.get(monitorId)
  }

  return {
    // 状态
    monitors,
    isUpdating,
    canvasRefs,
    // 计算属性
    canAddMore,
    // 动作
    addMonitors,
    removeMonitor,
    updateSignalInfo,
    showSignalAdder,
    drawTrendChart,
    onResetData,
    onInputData,
    onReconnected,
    setCanvasRef,
    getCanvasRef,
    loadFromLocalStorage  // 导出加载函数
  }
}) 